package com.dhcc.bpm.modules.api.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import org.springblade.core.mp.base.Excel;
import com.dhcc.bpm.common.utils.StringUtils;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;

/**
 * @Title
 * @ClassName PolicyItem
 * @Desription 报文策略详情表
 * @Author zhangzexu
 * @Date 2020/10/9 09:42
 * @Version V1.0
 */
@Data
@TableName("opc_policy_item")
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "opc_policy_item", description = "报文策略详情表")
public class PolicyItem extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /**
     * 关联OPC_POLICY_TAG表ID
     */
    @ApiModelProperty(value = "关联OPC_POLICY_TAG表ID")
    @Excel(name = "关联OPC_POLICY_TAG表ID")
    @JsonSerialize(using = ToStringSerializer.class, nullsUsing = NullSerializer.class)
    private Long policyTagId;
    /**
     * 关联OPC_API_METADATA表ID,用于记录映射关系
     */
    @ApiModelProperty(value = "关联OPC_API_METADATA表ID,用于记录映射关系")
    @Excel(name = "关联OPC_API_METADATA表ID,用于记录映射关系")
    @JsonSerialize(using = ToStringSerializer.class, nullsUsing = NullSerializer.class)
    private Long apiMetadataId;
    /**
     * 最顶级值默认为0,当出现复合结构及循环结构时使用此字段,代表此ITEM的上级ITEM_I
     */
    @ApiModelProperty(value = "最顶级值默认为0,当出现复合结构及循环结构时使用此字段,代表此ITEM的上级ITEM_I")
    @Excel(name = "最顶级值默认为0,当出现复合结构及循环结构时使用此字段,代表此ITEM的上级ITEM_I")
    @JsonSerialize(using = ToStringSerializer.class, nullsUsing = NullSerializer.class)
    private Long parentId;

    /**
     * path属性
     */
    @ApiModelProperty(value = "path属性")
    @Excel(name = "path属性")
    private String path;
    /**
     * name属性
     */
    @ApiModelProperty(value = "name属性")
    @Excel(name = "name属性")
    private String name;
    /**
     * cname属性
     */
    @ApiModelProperty(value = "cname属性")
    @Excel(name = "cname属性")
    private String chnName;

    /**
     * type属性
     */
    @ApiModelProperty(value = "type属性")
    @Excel(name = "type属性")
    private int type;

    /**
     * data_type属性
     */
    @ApiModelProperty(value = "data_type属性")
    @Excel(name = "data_type属性")
    private int dataType;

    /**
     * value属性
     */
    @ApiModelProperty(value = "value属性D")
    @Excel(name = "value属性")
    private String constantValue;

    /**
     * attr属性
     */
    @ApiModelProperty(value = "attr属性")
    @Excel(name = "attr属性")
    private String attribute;

    /**
     * addlen属性,0否1是,是否添加报文长度
     */
    @ApiModelProperty(value = "addlen属性,0否1是,是否添加报文长度")
    @Excel(name = "include属性,0否1是,是否包含长度本身长度")
    private int include;

    /**
     * addlen属性,0否1是,是否添加报文长度
     */
    @ApiModelProperty(value = "addlen属性,0否1是,是否添加报文长度")
    @Excel(name = "addlen属性,0否1是,是否添加报文长度")
    private int addLength;

    /**
     * addlenPosition属性,长度信息添加位置
     */
    @ApiModelProperty(value = "addlenPosition属性,长度信息添加位置")
    @Excel(name = "addlenPosition属性,长度信息添加位置")
    private int addLengthPos;

    /**
     * calculateLenPosition属性,计算组包后报文指定字节长度后的报文长度
     */
    @ApiModelProperty(value = "calculateLenPosition属性,计算组包后报文指定字节长度后的报文长度")
    @Excel(name = "calculateLenPosition属性,计算组包后报文指定字节长度后的报文长度")
    private int calcLengthPos;

    /**
     * index属性
     */
    @ApiModelProperty(value = "index属性")
    @Excel(name = "index属性")
    private int indexField;


    /**
     * beginIndex属性
     */
    @ApiModelProperty(value = "beginIndex属性")
    @Excel(name = "beginIndex属性")
    private int beginIndex;

    /**
     * len属性(有区间范围)
     */
    @ApiModelProperty(value = "len属性")
    @Excel(name = "len属性")
    private String length;

    /**
     * sep属性,分隔符
     */
    @ApiModelProperty(value = "sep属性,分隔符")
    @Excel(name = "sep属性,分隔符")
    private String separator;

    /**
     * breakSep属性,循环结束分割符
     */
    @ApiModelProperty(value = "breakSep属性,循环结束分割符")
    @Excel(name = "breakSep属性,循环结束分割符")
    private String breakSeparartor;

    /**
     * escape属性,0否1是,指定报文分隔符sep是否需要转义
     */
    @ApiModelProperty(value = "escape属性,0否1是,指定报文分隔符sep是否需要转义")
    @Excel(name = "escape属性,0否1是,指定报文分隔符sep是否需要转义")
    private int escapeField;

    /**
     * kbegin属性,key值前包字符
     */
    @ApiModelProperty(value = "kbegin属性,key值前包字符")
    @Excel(name = "kbegin属性,key值前包字符")
    private String kvBegin;

    /**
     * kend属性,key值后包字符
     */
    @ApiModelProperty(value = "kend属性,key值后包字符")
    @Excel(name = "kend属性,key值后包字符")
    private String kvEnd;


    /**
     * fillString属性,补位字符'
     */
    @ApiModelProperty(value = "fillString属性,补位字符'")
    @Excel(name = "fillString属性,补位字符'")
    private String fillString;

    /**
     * fillLen属性,补位长度
     */
    @ApiModelProperty(value = "fillLen属性,补位长度")
    @Excel(name = "fillLen属性,补位长度")
    private int fillLength;

    /**
     * fillType属性,0左1右,左右补位
     */
    @ApiModelProperty(value = "fillType属性,0左1右,左右补位")
    @Excel(name = "fillType属性,0左1右,左右补位")
    private int fillType;

    /**
     * 用于指定循环次数，loopName的属性值和某个item的name属性值相等
     */
    @ApiModelProperty(value = "循环次数")
    @Excel(name = "循环次数")
    private String loopName;


    /**
     * organize属性,0否1是,XML组包时此值等于N且value为空,此ITEM不处理
     */
    @ApiModelProperty(value = "organize属性,0否1是,XML组包时此值等于N且value为空,此ITEM不处理")
    @Excel(name = "organize属性,0否1是,XML组包时此值等于N且value为空,此ITEM不处理")
    private int organize;

    /**
     * struct属性,0否1是,8583是否有子域
     */
    @ApiModelProperty(value = "struct属性,0否1是,8583是否有子域")
    @Excel(name = "struct属性,0否1是,8583是否有子域")
    private int struct;

    /**
     * transform属性,0否1是,8583是否转换ascii码
     */
    @ApiModelProperty(value = "transform属性,0否1是,8583是否转换ascii码")
    @Excel(name = "transform属性,0否1是,8583是否转换ascii码")
    private int transform;

    /**
     * flag属性,0否1是,8583：是否占位
     */
    @ApiModelProperty(value = "flag属性,0否1是,8583：是否占位")
    @Excel(name = "flag属性,0否1是,8583：是否占位")
    private int occupy;

    /**
     * myself属性,false否true是,0-128指定域，是否包含长度域本身
     */
    @ApiModelProperty(value = "myself属性,false否true是,0-128指定域，是否包含长度域本身")
    @Excel(name = "myself属性,false否true是,0-128指定域，是否包含长度域本身")
    private String myself;

    /**
     * version属性,用于组包后在报文头部添加信息，一般用于xml报文
     */
    @ApiModelProperty(value = "version属性,用于组包后在报文头部添加信息，一般用于xml报文")
    @Excel(name = "version属性,用于组包后在报文头部添加信息，一般用于xml报文")
    private String version;

    /**
     * cdata属性,0否1是,用于xml报文
     */
    @ApiModelProperty(value = "cdata属性,0否1是,用于xml报文")
    @Excel(name = "cdata属性,0否1是,用于xml报文")
    private int cdata;
    /**
     * 是否循环 1 正常记录 2 循环记录
     **/
    @ApiModelProperty(value = "isLoop,0否1是,用于xml报文")
    @Excel(name = "isLoop,用于xml报文")
    private String isLoop;

    /**
     * 是否复合 1 变量 2 复合结构
     **/
    @ApiModelProperty(value = "isCompound,0否1是,用于xml报文")
    @Excel(name = "isCompound,用于xml报文")
    private String isCompound;


    /**
     * ignore属性,0否1是,此属性代表拆包后此ITEM值不放入JSON报文
     */
    @ApiModelProperty(value = "ignore属性,0否1是,此属性代表拆包后此ITEM值不放入JSON报文")
    @Excel(name = "ignore属性,0否1是,此属性代表拆包后此ITEM值不放入JSON报文")
    private int ignoreField;

    /**
     * ignore属性,0否1是,此属性代表拆包后此ITEM值不放入JSON报文
     */
    @ApiModelProperty(value = "8583 位图")
    @Excel(name = "8583 位图")
    private String bitmap;


    /**
     * <ITME>标签执行顺序
     */
    @ApiModelProperty(value = "<ITME>标签执行顺序")
    @Excel(name = "<ITME>标签执行顺序")
    private int orderField;

    /**
     * 备用字段1
     */
    @ApiModelProperty(value = "备用字段1")
    @Excel(name = "备用字段1")
    private String spare1;


    /**
     * 备用字段2
     */
    @ApiModelProperty(value = "备用字段2")
    @Excel(name = "备用字段2")
    private String spare2;


    @ApiModelProperty(value = "备注")
    @Excel(name = "备注")
    private String remark;

    @Excel(name = "jname")
    @ApiModelProperty(value = "jname")
    private String jname;

    private static final String DATA_TYPE = "datatype";
    private static final String MEATE_TYPE = "type";

    public String toString(int policyType, int tagType) {

        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append(formate("name", name));
        // 中文注释
        stringBuilder.append(formate("cname", chnName));
        //数据类型转化
        formateType(stringBuilder, type);
        //数据类型转化
        formateType(stringBuilder, dataType);
        //是否拼接jname
        isJname(stringBuilder, policyType, tagType);

        stringBuilder.append(formate("value", constantValue));
        stringBuilder.append(formate("include", include == 0 ? "N" : "Y"));
        stringBuilder.append(formate("addlen", addLength == 0 ? "N" : "Y"));
        stringBuilder.append(formate("addlenPosition", addLengthPos));
        stringBuilder.append(formate("calculateLenPosition", calcLengthPos));

        switch (policyType) {
            //JSON
            case 1:
                stringBuilder.append(formate("jname", jname));
                break;

            case 2:
                stringBuilder.append(formate("organize", organize == 0 ? "" : "Y"));
                stringBuilder.append(formate("path", path));
                stringBuilder.append(formate("attr", attribute));
                stringBuilder.append(formate("version", version));
                stringBuilder.append(formate("cdata", cdata));
                break;
            //分隔
            case 3:
                stringBuilder.append(formate("sep", separator));
                stringBuilder.append(formate("escape", escapeField));
                stringBuilder.append(formate("beginIndex", beginIndex));
                break;
            //定长
            case 4:
                stringBuilder.append(formate("fillLen", fillLength));
                stringBuilder.append(formate("beginIndex", beginIndex));
                break;
            //8583
            case 5:
                stringBuilder.append(formate("begin", beginIndex));
                stringBuilder.append(formate("index", indexField));
                stringBuilder.append(formate("struct", struct));
                stringBuilder.append(formate("transform", transform));
                stringBuilder.append(formate("flag", occupy));
                stringBuilder.append(formate("myself", myself));
                stringBuilder.append(formate("bitmap", bitmap));
                break;
            default:
                break;
        }


        //  LastWork 定长 必填,其他0 默认
        if (tagType == 4) {
            if (5 == policyType) {
                stringBuilder.append(formate("length", length));
            } else {
                stringBuilder.append(formate("len", length));
            }
        } else {
            stringBuilder.append(formate("len", length.equals("0") ? "" : length));
        }
        stringBuilder.append(formate("kbegin", kvBegin));
        stringBuilder.append(formate("kend", kvEnd));
        stringBuilder.append(formate("fillString", fillString));
        stringBuilder.append(formate("fillType", fillType == 0 ? "" : "R"));
        stringBuilder.append(formate("loopName", loopName));
        stringBuilder.append(formate("ignore", ignoreField == 0 ? "" : "Y"));
        return stringBuilder.toString();
    }

    private String formate(String key, String value) {

        if (StringUtils.isNotEmpty(value)) {
            return String.format(" %s=\"%s\"", key, value);
        } else {
            return "";
        }
    }

    private String formate(String key, Integer value) {
        if (0 == value) {
            return "";
        } else {
            return String.format(" %s=\"%s\"", key, value);
        }

    }

    private void formateType(StringBuilder stringBuilder, int type) {
        if (type == 2) {
            stringBuilder.append(formate(MEATE_TYPE, "Integer"));
        } else if (type == 3) {
            stringBuilder.append(formate(MEATE_TYPE, "Float"));
        } else if (type == 4) {
            stringBuilder.append(formate(MEATE_TYPE, "Double"));
        } else if (type == 5) {
            stringBuilder.append(formate(MEATE_TYPE, "BigDecimal"));
        } else if (type == 6) {
            stringBuilder.append(formate(MEATE_TYPE, "BigInteger"));
        } else if (type == 7) {
            stringBuilder.append(formate(MEATE_TYPE, "Object"));
        } else if (type == 8) {
            stringBuilder.append(formate(MEATE_TYPE, "List"));
        }
    }


    public String isJname(StringBuilder stringBuilder, int policyType, int tagType) {
        if (policyType == 1 && tagType == 3) {
            stringBuilder.append(formate("jname", jname));
            return stringBuilder.toString();
        }
        return stringBuilder.toString();
    }
}
